<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
    <!-- <meta http-equiv="refresh" content="5"> -->
    <script src="js/utils.js"></script>
    <script src="js/lodash.js"></script>
    <script src="js/index.js"></script>
    <script src="js/tools.js"></script>
</head>
<body>
<script>
  /*// 通过随机数算π值
  let count = 0
  const time = 1000000
  for (let i = 0; i < time; i++) {
      const x = Math.random()
      const y = Math.random()
      if (Math.sqrt(x * x + y * y) <= 1) {
          count++
      }
  }
  console.log((count / time * 4).toFixed(2))*/
</script>
<script>
  /*// 两周调用方法实现求和
  function add(x, y) {
      if (arguments.length === 1) {
          return z => {
              return x + z
          }
      } else {
          return x + y
      }
  }

  console.log(add(1, 2));
  console.log(add(3)(4));*/
</script>
<script>
  /*// for of实现遍历对象
  const obj = {
      a: 1,
      b: 2,
      c: 3,
      __proto__: {
          [Symbol.iterator]() {
              const keys = Object.keys(this)
              let count = 0
              return {
                  next() {
                      if (count < keys.length) {
                          return {
                              value: obj[keys[count++]],
                              done: false
                          }
                      } else {
                          return {
                              value: undefined,
                              done: true
                          }
                      }
                  }
              }
          }
      }
  }
  for (const i of obj) {
      console.log(i);
  }*/
</script>
<script>
  /*// 各种方法求数组最大值
  const arr = [32, 12, 8, 19, 38, 100, 45]
  // 1.max
  const max1 = Math.max(...arr)
  // 2.apply
  const max2 = Math.max.apply(null, arr)
  // 3.sort
  arr.sort((n1, n2) => n2 - n1)
  const max3 = arr[0]
  // 4.reduce
  const max4 = arr.reduce((n1, n2) => n1 > n2 ? n1 : n2)
  // 循环
  let max5 = arr[0]
  for (let i = 0; i < arr.length; i++) {
      max5 = max5 < arr[i + 1] ? arr[i + 1] : max5
  }

  // 递归1
  function findMax1(arr) {
      if (arr.length === 0) return undefined
      else if (arr.length === 1) return arr[0]
      const len = Math.ceil(arr.length / 2)
      const leftArr = arr.slice(0, len)
      const rightArr = arr.slice(len)
      const leftMax = findMax1(leftArr)
      const rightMax = findMax1(rightArr)
      if (leftMax >= rightMax) return leftMax
      else return rightMax
  }

  const max6 = findMax1(arr)
  // 递归2
  let max7 = arr[0]

  function findMax2(i) {
      if (i === arr.length) return max7
      if (max7 < arr[i]) max7 = arr[i]
      findMax2(i + 1)
  }

  findMax2(1)

  console.log(max1)
  console.log(max2)
  console.log(max3)
  console.log(max4)
  console.log(max5)
  console.log(max6)
  console.log(max7)*/
</script>
<script>
  /*// 各种方法反转数组
  const arr = [25, 8, 19, 28, 22]
  // 1
  const newArr1 = []
  arr.forEach(item => {
      newArr1.unshift(item)
  })
  // 2
  const newArr2 = []
  for (let i = arr.length - 1; i >= 0; i--) {
      newArr2.push(arr[i])
  }

  // 3
  function reverse(arr) {
      if (arr.length === 0) return []
      let first = arr[0]
      return [...reverse(arr.slice(1)), first]
  }

  const newArr3 = reverse(arr)

  console.log(newArr1)
  console.log(newArr2)
  console.log(newArr3)*/
</script>
<script>
  /*// 当a=？时，下面等式成立
  // 1
  let a1 = {
      num: 0,
      toString() {
          return ++this.num
      }
  }
  // 2
  let a2 = [1, 2, 3]
  a2.join = a2.shift
  if (a1 == 1 && a1 == 2 && a1 == 3) {
      console.log(1);
  }
  if (a2 == 1 && a2 == 2 && a2 == 3) {
      console.log(1);
  }*/
</script>
<script>
  /*// 模拟一个new方法
  function _new(fn, ...args) {
      // const obj = {}
      // obj.__proto__ = constructor.prototype
      const obj = Object.create(fn.prototype)
      const result = fn.apply(obj, args)
      return Object.prototype.toString.call(result) === '[object Object]' ? result : obj
  }

  function Person(name) {
      this.name = name
      // this.say = function () {
      //     console.log(1)
      // }
  }

  Person.prototype.say = function () {
      console.log(this.name)
  }

  let person = _new(Person, 'abc')
  person.say()*/
</script>
<script>
  /*// 原型及原型链关系
  function Person(name) {
      this.name = name
  }
  const person = new Person('abc')
  console.log(person.__proto__ === Person.prototype)

  console.log(Person.__proto__ === Function.prototype)
  console.log(Object.__proto__ === Function.prototype)
  console.log(Function.__proto__ === Function.prototype)

  console.log(Person.prototype.constructor === Person)
  console.log(Object.prototype.constructor === Object)
  console.log(Function.prototype.constructor === Function)

  console.log(Person.prototype.__proto__ === Object.prototype)
  console.log(Function.prototype.__proto__ === Object.prototype)
  console.log(Object.prototype.__proto__ === null)*/
</script>
<script>
  /*// 模拟一个instanceof方法
  function instance_of(L, R) {
      const types = [String, Number, Boolean, Object, Array, Function, Symbol, Set, Map, WeakSet, WeakMap]
      if (typeof R !== 'object' && typeof R !== 'function') {
          throw new TypeError("Right-hand side of 'instanceof' is not an object")
      } else if (!types.includes(R)) {
          throw new TypeError("Right-hand side of 'instanceof' is not callable")
      }
      if (typeof L !== 'object' && typeof L !== 'function') return false
      if (L === null) return false
      let proto = L.__proto__
      const prototype = R.prototype
      while (true) {
          if (proto === null) return false
          if (proto === prototype) return true
          proto = proto.__proto__
      }
  }

  const obj = {}
  const arr = []
  const fn = function () {
  }
  console.log(instance_of(obj, Object))
  console.log(instance_of(arr, Object))
  console.log(instance_of(fn, Object))*/
</script>
<script>
  /*// reduce使用方法
  // 求和
  const arr1 = [1, 2, 3, 4, 5, 6, 7]
  const res1 = arr1.reduce((a, i) => a + i)
  console.log(res1)
  // 求最大值
  const arr2 = [1, 2, 3, 4, 5, 6, 7]
  const res2 = arr2.reduce((a, i) => Math.max(a, i))
  console.log(res2)
  // 数组去重
  const arr3 = [1, 2, 3, 'a', 'b', 'c', 1, 2, 3]
  const res3 = arr3.reduce((a, b) => {
      if (a.indexOf(b) === -1) {
          a.push(b)
      }
      return a
  }, [])
  console.log(res3)
  // 根据字段分类
  const arr4 = [
      {name: 'Lily', job: 'Web', country: 'China'},
      {name: 'Bob', job: 'Java', country: 'China'},
      {name: 'Tom', job: 'Python', country: 'USA'},
      {name: 'Jim', job: 'GoLang', country: 'UK'}
  ]
  const res4 = arr4.reduce((group, cur) => {
      const newKey = cur['country']
      if (!group[newKey]) {
          group[newKey] = []
      }
      group[newKey].push(cur)
      return group
  }, [])
  console.log(res4)
  // 数组扁平化(一层)
  const arr5 = [[1, 2, 3], [4], [5, 6]]
  const res5 = arr5.reduce((a, b) => a.concat(b), [])
  console.log(res5)*/
</script>
<script>
  /*// 深拷贝
  function deepClone(target, map = new WeakMap()) {
      const typeArr = [RegExp, Set, Map, WeakSet, WeakMap, Date, Error]
      if (map.has(target)) return map.get(target)
      if (target instanceof Object) {
          let dist
          if (target instanceof Array) {
              dist = []
          } else if (typeArr.includes(target.constructor)) {
              dist = new target.constructor(target)
          } else if (target && typeof target === 'object') {
              dist = {}
          } else {
              dist = target
          }
          map.set(target, dist)
          for (let key in target) {
              if (target.hasOwnProperty(key)) {
                  dist[key] = deepClone(target[key], map)
              }
          }
          return dist
      } else {
          return target
      }
  }

  const obj1 = {
      a: 1,
      b: new Date().getTime(),
      c: new Set([1, 2]),
      d: [1, 2, 3],
      e: function () {
      },
      f: {
          a: 1,
          b: 2
      }
  }
  const obj2 = deepClone(obj1)
  obj1.a = 19
  console.log(obj1)
  console.log(obj2)*/
</script>
<script>
  /*// 防抖和节流
  // 防抖
  function debounce(fn, timeout) {
      let timer = null
      return function (...args) {
          clearTimeout(timer)
          timer = setTimeout(() => {
              fn && fn.apply(this, args)
          }, timeout)
      }
  }

  // 节流
  function throttle(fn, timeout) {
      let timer = null
      return function (...args) {
          if (timer) return
          timer = setTimeout(() => {
              fn && fn.apply(this, args)
              timer = null
          }, timeout)
      }
  }*/
</script>
<script>
  /*// 数组转树和树转数组
  const arr = [
      {name: '小明', id: 1, pid: 0},
      {name: '小花', id: 11, pid: 1},
      {name: '小华', id: 111, pid: 11},
      {name: '小李', id: 112, pid: 11},
      {name: '小红', id: 12, pid: 1},
      {name: '小王', id: 2, pid: 0},
      {name: '小周', id: 21, pid: 2},
      {name: '小鹏', id: 22, pid: 2},
  ]
  // 数组转树
  // 1
  function arrayToTree1(arr) {
      const result = []
      const itemMap = {}
      for (const item of arr) {
          itemMap[item.id] = {...item, children: []}
      }
      for (const item of arr) {
          const id = item.id
          const pid = item.pid
          const treeItem = itemMap[id]

          if (pid === 0) {
              result.push(treeItem)
          } else {
              if (!itemMap[id]) {
                  itemMap[pid] = {
                      children: []
                  }
              }
              itemMap[pid].children.push(treeItem)
          }
      }
      return result
  }

  // 2
  function arrayToTree2(arr, pid) {
      const res = []
      arr.forEach(item => {
          if (item.pid === pid) {
              const itemChildren = arrayToTree2(arr, item.id)
              if (itemChildren.length > 0) {
                  item.children = itemChildren
              }
              res.push(item)
          }
      })
      return res
  }

  // 树转数组
  // 1
  function treeToArray1(tree) {
      const stack = tree
      const result = []
      while (stack.length !== 0) {
          let pop = stack.pop()
          result.push({
              id: pop.id,
              name: pop.name,
              pid: pop.pid
          })
          const children = pop.children
          if (children) {
              for (let i = children.length - 1; i >= 0; i--) {
                  stack.push(children[i])
              }
          }
      }
      return result
  }

  // 2
  function treeToArray2(tree) {
      const queue = tree
      const result = []
      while (queue.length !== 0) {
          const shift = queue.shift()
          result.push({
              id: shift.id,
              name: shift.name,
              pid: shift.pid
          })
          const children = shift.children
          if (children) {
              for (let i = 0; i < children.length; i++) {
                  queue.push(children[i])
              }
          }
      }
      return result
  }

  console.log(arrayToTree1(arr))
  console.log(arrayToTree2(arr, 0))
  console.log(treeToArray1(arrayToTree1(arr)))
  console.log(treeToArray2(arrayToTree2(arr, 0)))*/
</script>
<script>
  /*// 以第二个数最早结束为准
  function twoSum1(nums, target) {
      const myMap = new Map()
      for (let i = 0; i < nums.length; i++) {
          const reverse = target - nums[i]
          if (myMap.has(reverse)) {
              return [myMap.get(reverse), i]
          }
          myMap.set(nums[i], i)
      }
      return null
  }

  // 以第一个数为准，找第二个数
  function twoSum2(nums, target) {
      for (let i = 0; i < nums.length; i++) {
          for (let j = i + 1; j < nums.length; j++) {
              if (nums[j] === target - nums[i]) {
                  return [i, j]
              }
          }
      }
      return null
  }

  const res1 = twoSum1([2, 3, 8, 1, 7, 3, 4, 4, 2, 1, 5, 6, 5, 7, 8, 6], 7)
  const res2 = twoSum2([2, 3, 8, 1, 7, 3, 4, 4, 2, 1, 5, 6, 5, 7, 8, 6], 7)
  console.log(res1)
  console.log(res2)*/
</script>
<script>
  // 两种方法实现0-9每隔一秒输出
  /*function request1(i) {
      return new Promise(resolve => {
          setTimeout(() => {
              resolve(i)
          }, 1000 * (i + 1))
      })
  }

  for (let i = 0; i < 10; i++) {
      request1(i).then(res => {
          console.log(res)
      })
  }*/

  /*async function request2() {
      return new Promise(resolve => {
          setTimeout(() => {
              resolve()
          }, 1000)
      })
  }

  (async () => {
      for (let i = 0; i < 10; i++) {
          await request2()
          console.log(i)
      }
  })()*/
</script>
<script>
  /*let data = [
      {count: 1, name: 'name1', day: 20220418},
      {count: 11, name: 'name2', day: 20220418},
      {count: 22, name: 'name2', day: 20220419},
      {count: 2, name: 'name3', day: 20220419},
      {count: 3, name: 'name1', day: 20220420},
      {count: 33, name: 'name3', day: 20220420},
      {count: 4, name: 'name1', day: 20220421},
      {count: 5, name: 'name1', day: 20220422},
      {count: 555, name: 'name2', day: 20220422},
      {count: 55, name: 'name3', day: 20220422},
  ]
  let allData = []
  while (data.length > 0) {
      let obj = data[0]
      let count = 0
      let resData = []
      for (let i = 1; i < data.length; i++) {
          if (obj.day === data[i].day) {
              count++
          }
      }
      if (count === 0) {
          const targetObj = {
              day: obj.day,
              arr: [{name: obj.name, count: obj.count}]
          }
          if (obj.name === 'name1') {
              targetObj.arr.push({name: 'name2', count: 0})
              targetObj.arr.push({name: 'name3', count: 0})
          } else if (obj.name === 'name2') {
              targetObj.arr.unshift({name: 'name1', count: 0})
              targetObj.arr.push({name: 'name3', count: 0})
          } else if (obj.name === 'name3') {
              targetObj.arr.unshift({name: 'name2', count: 0})
              targetObj.arr.unshift({name: 'name1', count: 0})
          }
          resData = targetObj
      } else if (count > 0) {
          const targetObj = {
              day: obj.day,
              arr: []
          }
          if (count === 1) {
              const nameArr = [data[0].name, data[1].name]
              targetObj.arr.push({name: data[0].name, count: data[0].count})
              targetObj.arr.push({name: data[1].name, count: data[1].count})
              if (nameArr.indexOf('name1') === -1) {
                  targetObj.arr.unshift({name: 'name1', count: 0})
              } else if (nameArr.indexOf('name2') === -1) {
                  targetObj.arr.splice(1, 0, {name: 'name2', count: 0})
              } else if (nameArr.indexOf('name3') === -1) {
                  targetObj.arr.push({name: 'name3', count: 0})
              }
          } else if (count === 2) {
              for (let i = 0; i < 3; i++) {
                  targetObj.arr.push({name: data[i].name, count: data[i].count})
              }
          }
          resData = targetObj
      }
      data = data.slice(count + 1)
      allData.push(resData)
  }
  console.log(allData);*/
</script>
<script>
  /*const oldArr = [
      {
          id: 1,
          name: 'abc',
          isOpen: true,
          children: [
              {
                  id: 11,
                  name: 'ddd',
                  isOpen: true
              }
          ]
      },
      {
          id: 2,
          name: 'def',
          isOpen: true
      }
  ]
  const newArr = [
      {
          id: 1,
          name: 'abc'
      },
      {
          id: 2,
          name: 'def'
      },
      {
          id: 3,
          name: 'ghi'
      }
  ]
  const set = new Set(oldArr.map(item => item.id))
  const map = new Map(newArr.map(item => ([item.id, item])))
  const res = oldArr.map(item => {
      if (map.has(item.id)) {
          return {...item, ...map.get(item.id)}
      }
      return {...item}
  }).concat(...newArr.filter(item => !set.has(item.id)))
  console.log(res);*/
</script>
<script>
  /*const num = 23
  const style = 'color: red; font-size: 24px; background-color: yellowgreen; padding: 0 6px;'
  console.log(`%c${num}`, style)*/
</script>
<script>
  /*const obj = {}
  console.log(Reflect.ownKeys(obj).length === 0 && obj.constructor === Object)
  const arr1 = [1, 4, 6, 3, 7, 9, 3, 6]
  const arr2 = [3, 7, 9]
  const res1 = arr1.filter(item => item % 2 === 0)
  const res2 = arr1.filter(item => arr2.includes(item))
  const res3 = arr1.filter(item => !arr2.includes(item))
  console.log(res1)
  console.log(res2)
  console.log(res3)
  const arr3 = [1, [2, 3, [4, 5, 6], [[7, 8]], 9], 10]

  function flatten1(arr) {
      while (arr.some(item => Array.isArray(item))) {
          arr = [].concat(...arr)
      }
      return arr
  }

  function flatten2(arr) {
      let result = []
      for (let i = 0; i < arr.length; i++) {
          if (Array.isArray(arr[i])) {
              result = result.concat(flatten2(arr[i]))
          } else {
              result.push(arr[i])
          }
      }
      return result
  }

  function flatten3(arr, deep = 1) {
      if (deep <= 0) return arr
      return arr.reduce((res, cur) => res.concat(Array.isArray(cur) ? flatten3(cur, deep - 1) : cur), [])
  }

  console.log(arr3.flat(Infinity))
  console.log(flatten1(arr3))
  console.log(flatten2(arr3))
  console.log(flatten3(arr3, Infinity))

  const generateRandomHexColor = () => `#${Math.floor(Math.random() * 0xffffff).toString(16)}`
  console.log(generateRandomHexColor())
  if ((obj ?? '') !== '') {
      console.log('不是空字符串、null或undefined')
  }*/
</script>
<script>
  /*const arr = ['1', 1, true, undefined, 1, 0, {a: 1, b: 2}, {a: 1, c: 3}, {b: 1, c: 2}, {
    a: 1,
    b: 2
  }, new Set([1, 2]), new Set([1, 2])]
  console.log(_.uniqWith(arr, _.isEqual))
  console.log(dataList())*/
</script>
<script>
  /*const oldData = {
    "taskName": "新增",
    "roadConditionRoads": [
      {
        "delete": null,
        "roadName": "11",
        "roadDirection": "1",
        "roadTravelRuleList": [
          {
            "vehicleType": "1",
            "travelStatus": "1"
          },
          {
            "vehicleType": "2",
            "travelStatus": "1"
          },
          {
            "vehicleType": "3",
            "travelStatus": "2"
          },
          {
            "vehicleType": "4",
            "travelStatus": "1"
          },
          {
            "vehicleType": "5",
            "travelStatus": "1"
          }
        ],
        "remark": "",
        "points": [
          [
            109.89647816094978,
            39.61807226724908
          ],
          [
            109.89636774574268,
            39.61717165778483
          ]
        ],
        "geoJson": "{\"coordinates\":[[109.896492,39.618069]],\"type\":\"LineString\"}"
      },
      {
        "delete": null,
        "roadName": "新增22",
        "roadDirection": "2",
        "roadTravelRuleList": [
          {
            "vehicleType": "1",
            "travelStatus": "1"
          },
          {
            "vehicleType": "2",
            "travelStatus": "1"
          },
          {
            "vehicleType": "3",
            "travelStatus": "3"
          },
          {
            "vehicleType": "4",
            "travelStatus": "2"
          },
          {
            "vehicleType": "5",
            "travelStatus": "3"
          }
        ],
        "remark": "",
        "points": [
          [
            109.9104738180294,
            39.61621884245109
          ],
          [
            109.91024703388976,
            39.61575594273285
          ]
        ],
        "geoJson": "{\"coordinates\":[[109.913353,39.614841],[109.913116,39.61438]],\"type\":\"LineString\"}"
      }
    ]
  }
  const newData = {
    "taskName": "测试22",
    "roadConditionTaskId": "360f8b3b79852206f803d6f6c8dd7a0f",
    "roadConditionRoads": [
      {
        "delete": null,
        "geoJson": "{\"coordinates\":[[109.896492,39.628069]],\"type\":\"LineString\"}",
        "remarks": 'abcdef',
        "roadConditionRoadId": "21f08171-ee55-4451-aa1f-a0e620630266",
        "roadDirection": "1",
        "roadName": "11",
        "roadTravelRuleList": [
          {
            "roadConditionRoadId": "21f08171-ee55-4451-aa1f-a0e620630266",
            "roadConditionTravelRuleId": "ece4ac1d4a186c38d796c5e78603db1d",
            "travelStatus": "1",
            "vehicleType": "1"
          },
          {
            "roadConditionRoadId": "21f08171-ee55-4451-aa1f-a0e620630266",
            "roadConditionTravelRuleId": "c196b0930c4ff22148f7743950d37e49",
            "travelStatus": "1",
            "vehicleType": "2"
          },
          {
            "roadConditionRoadId": "21f08171-ee55-4451-aa1f-a0e620630266",
            "roadConditionTravelRuleId": "94006251e3a5db3dfafcfa63c3e5fb3d",
            "travelStatus": "1",
            "vehicleType": "3"
          },
          {
            "roadConditionRoadId": "21f08171-ee55-4451-aa1f-a0e620630266",
            "roadConditionTravelRuleId": "00132a9217358d8745045f816a281023",
            "travelStatus": "1",
            "vehicleType": "4"
          },
          {
            "roadConditionRoadId": "21f08171-ee55-4451-aa1f-a0e620630266",
            "roadConditionTravelRuleId": "6be6355d29791f638ced52c8986774bb",
            "travelStatus": "1",
            "vehicleType": "5"
          }
        ],
        "wkt": null
      },
      {
        "delete": 1,
        "geoJson": "{\"coordinates\":[[109.914574,39.715679],[109.914589,39.715618],[109.914711,39.715248]],\"type\":\"LineString\"}",
        "remarks": null,
        "roadConditionRoadId": "27546d25-8476-451a-a40e-ea220357f0e2",
        "roadDirection": "1",
        "roadName": "456",
        "roadTravelRuleList": [
          {
            "roadConditionRoadId": "27546d25-8476-451a-a40e-ea220357f0e2",
            "roadConditionTravelRuleId": "c9a39778e3f80e7fc709afd84497b685",
            "travelStatus": "2",
            "vehicleType": "2"
          },
          {
            "roadConditionRoadId": "27546d25-8476-451a-a40e-ea220357f0e2",
            "roadConditionTravelRuleId": "19422c02bb65351763ad04f626a40cb2",
            "travelStatus": "2",
            "vehicleType": "2"
          },
          {
            "roadConditionRoadId": "27546d25-8476-451a-a40e-ea220357f0e2",
            "roadConditionTravelRuleId": "55531bff8ca168ed3fdd0636d901a183",
            "travelStatus": "1",
            "vehicleType": "3"
          },
          {
            "roadConditionRoadId": "27546d25-8476-451a-a40e-ea220357f0e2",
            "roadConditionTravelRuleId": "445a3a8f283ecc61f2cbad5acff0112b",
            "travelStatus": "2",
            "vehicleType": "4"
          },
          {
            "roadConditionRoadId": "27546d25-8476-451a-a40e-ea220357f0e2",
            "roadConditionTravelRuleId": "edd05fa0675f193819fa9bd466298bef",
            "travelStatus": "3",
            "vehicleType": "5"
          }
        ],
        "wkt": null
      },
      {
        "delete": null,
        "roadName": "newABC",
        "roadDirection": "1",
        "roadTravelRuleList": [
          {
            "vehicleType": "1",
            "travelStatus": "1"
          },
          {
            "vehicleType": "2",
            "travelStatus": "1"
          },
          {
            "vehicleType": "3",
            "travelStatus": "2"
          },
          {
            "vehicleType": "4",
            "travelStatus": "1"
          },
          {
            "vehicleType": "5",
            "travelStatus": "1"
          }
        ],
        "remark": "remark11",
        "points": [
          [
            109.89647816094978,
            39.61807226724908
          ],
          [
            109.89636774574268,
            39.61717165778483
          ]
        ],
        "geoJson": "{\"coordinates\":[[110.896492,38.618069]],\"type\":\"LineString\"}"
      },
    ],
  }
  const res = filterData(oldData, newData)
  console.log(res)*/
</script>
</body>
</html>
